﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.Web;
using System.Security.Permissions;
using System.Web.Configuration;
using TallComponents.Web.Pdf.Resources;
using System.Configuration.Provider;

namespace TallComponents.Web.Storage
{
   /// <summary>
   /// Configuration section for <see cref="PdfStorageProvider"/>.
   /// </summary>
   /// <remarks>
   /// The following configuration example shows how to setup a filesystem-based pdf storage provider as the default
   /// provider.
   /// <example><code lang="xml">
   /// &lt;?xml version="1.0"?&gt;
   ///   &lt;configuration&gt;
   ///      &lt;section name="pdfStorage" type="TallComponents.Web.Storage.PdfStorageProviderSection,TallComponents.Web.PdfViewer" /&gt;
   ///   &lt;/configSections&gt;
   ///   &lt;pdfStorage defaultProvider="filesystem">
   ///     &lt;providers&gt;
   ///       &lt;clear /&gt;
   ///       &lt;add name="filesystem" type="TallComponents.Web.Storage.FileSystemStorageProvider,TallComponents.Web.PdfViewer" basePath="~/documents"/&gt;
   ///     &lt;/providers&gt;
   ///   &lt;/pdfStorage&gt;
   /// </code></example>
   /// </remarks>   
#if !(NET40)
   [AspNetHostingPermission( SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal )]
#endif
   public sealed class PdfStorageProviderSection : ConfigurationSection
   {
      // Fields
      private static readonly ConfigurationProperty _propDefaultProvider = new ConfigurationProperty( "defaultProvider", typeof( string ), "DefaultPdfStorageProvider", null, new StringValidator(1), ConfigurationPropertyOptions.None );
      private static readonly ConfigurationProperty _propEnabled = new ConfigurationProperty( "enabled", typeof( bool ), true, ConfigurationPropertyOptions.None );
      private static readonly ConfigurationPropertyCollection _properties = new ConfigurationPropertyCollection();
      private static readonly ConfigurationProperty _propProviders = new ConfigurationProperty( "providers", typeof( ProviderSettingsCollection ), null, ConfigurationPropertyOptions.None );

      /// <summary>
      /// Initializes the <see cref="PdfStorageProviderSection"/> class.
      /// </summary>
      static PdfStorageProviderSection()
      {
         _properties.Add( _propDefaultProvider );
         _properties.Add( _propEnabled );
         _properties.Add( _propProviders );
      }

      /// <summary>
      /// Validates the default provider.
      /// </summary>
      internal void ValidateDefaultProvider()
      {
         if ( !string.IsNullOrEmpty( DefaultProvider ) && ( Providers[ DefaultProvider ] == null ) )
         {
            var nameProp = ElementInformation.Properties[ _propDefaultProvider.Name ];

            throw new ConfigurationErrorsException( 
               String.Format( Text.Config_provider_must_exist, DefaultProvider ), 
                  nameProp != null ? nameProp.Source : "", nameProp != null ? nameProp.LineNumber : 0 );
         }
      } 

      /// <summary>
      /// Gets or sets the name of the default provider.
      /// </summary>
      /// <value>The name of the default provider.</value>
      [StringValidator( MinLength = 1 )]
      [ConfigurationProperty( "defaultProvider", DefaultValue = "DefaultPdfStorageProvider" )]
      public string DefaultProvider
      {
         get
         {
            return ( string )base[ _propDefaultProvider ];
         }
         set
         {
            base[ _propDefaultProvider ] = value;
         }
      }

      /// <summary>
      /// Gets or sets a value indicating whether this <see cref="PdfStorageProviderSection"/> is enabled.
      /// </summary>
      /// <value><c>true</c> if enabled; otherwise, <c>false</c>.</value>
      [ConfigurationProperty( "enabled", DefaultValue = true )]
      public bool Enabled
      {
         get
         {
            return ( bool )base[ _propEnabled ];
         }
         set
         {
            base[ _propEnabled ] = value;
         }
      }

      /// <summary>
      /// Gets the collection of properties.
      /// </summary>
      /// <value></value>
      /// <returns>
      /// The <see cref="T:System.Configuration.ConfigurationPropertyCollection"/> of properties for the element.
      /// </returns>
      protected override ConfigurationPropertyCollection Properties
      {
         get
         {
            return _properties;
         }
      }

      /// <summary>
      /// Gets the providers.
      /// </summary>
      /// <value>The providers.</value>
      [ConfigurationProperty( "providers" )]
      public ProviderSettingsCollection Providers
      {
         get
         {
            return ( ProviderSettingsCollection )base[ _propProviders ];
         }
      }

      /// <summary>
      /// Gets the providers internal.
      /// </summary>
      /// <value>The providers internal.</value>
      internal Dictionary<string, PdfStorageProvider> ProvidersInternal
      {
         get
         {
            if ( _providers == null )
            {
               lock ( this )
               {
                  if ( _providers == null )
                  {
                     var providers = new ProviderCollection();
                     ProvidersHelper.InstantiateProviders( Providers, providers, typeof( PdfStorageProvider ) );
                     _providers = new Dictionary<string,PdfStorageProvider>();
                     foreach ( PdfStorageProvider item in providers )
                     {
                        _providers.Add( item.Name, item );
                     }
                  }
               }
            }
            return _providers;
         }
      }

      private Dictionary<string, PdfStorageProvider> _providers;
   }
}
